/*
 *******************************************************************
 * Author: xuelei
 * Create Date: 2021-09-09 14:13
 * Description: create file
 *******************************************************************
 */
package com.xuelei.cloud.bc.hash;

import com.xuelei.cloud.bc.Checker;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.util.encoders.Hex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

/**
 * 基于SM3算法的摘要工具类
 * @author xuelei
 * @date 2021-09-09
 */
public class SM3Util {
    
    private static final Logger log = LoggerFactory.getLogger(SM3Util.class);
    
    private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
    
    /**
     * 计算特定字符串的摘要信息
     * @param srcText 原始字符串
     * @return Base16编码的摘要值
     */
    public static String digest(String srcText) {
        Checker.checkText(srcText, "src text is empty");
        byte[] dataBlock = srcText.getBytes(DEFAULT_CHARSET);
        return digest(dataBlock);
    }
    
    /**
     * 计算特定数据块的摘要信息
     * @param dataBlock 原始数据块
     * @return Base16编码的摘要值
     */
    public static String digest(byte[] dataBlock) {
        Checker.checkBlock(dataBlock, "data block is empty");
        SM3Digest sm3Digest = new SM3Digest();
        sm3Digest.update(dataBlock, 0, dataBlock.length);
        byte[] hash = new byte[sm3Digest.getDigestSize()];
        sm3Digest.doFinal(hash, 0);
        return Hex.toHexString(hash);
    }
    
    /**
     * 检查给定的字符串的摘要信息，与给定的摘要值是否匹配
     * @param srcText 待检查的字符串
     * @param sm3DigestBase16 基于SM3计算的Base16编码的摘要值
     * @return 匹配结果
     */
    public static boolean verify(String srcText, String sm3DigestBase16) {
        Checker.checkText(srcText, "src text is empty");
        Checker.checkText(sm3DigestBase16, "digest text is empty");
        return verify(srcText.getBytes(DEFAULT_CHARSET), sm3DigestBase16);
    }
    
    /**
     * 检查给定的数据块的摘要信息，与给定的摘要值是否匹配
     * @param dataBlock 待检查的数据块
     * @param sm3DigestBase16 基于SM3计算的Base16编码的摘要值
     * @return 匹配结果
     */
    public static boolean verify(byte[] dataBlock, String sm3DigestBase16) {
        Checker.checkBlock(dataBlock, "data block is empty");
        Checker.checkText(sm3DigestBase16, "digest text is empty");
        String digest = digest(dataBlock);
        if (log.isDebugEnabled()) {
            log.debug("srcDataDigestBase16: {}", Hex.toHexString(dataBlock));
            log.debug("givenDigestBase16: {}", sm3DigestBase16);
        }
        return digest.equals(sm3DigestBase16);
    }
}
